export const vsSource = `
precision highp float;
in float position;
out vec2 v_textureCoords;
out vec3 v_normalEC;
out vec3 v_positionEC;
out vec4 v_color;
out vec3 v_positionMC;

vec2 getUV(vec2 lonlat0) {
  vec4 worldExtent = Weget_extent();
  bool shouldFlipY = Weget_shouldFlipY() > 0.0;
  vec2 ws = worldExtent.xy;
  vec2 en = worldExtent.zw;
  vec2 uv = (lonlat0 - ws) / (en - ws);
  if(shouldFlipY){
    uv.y = 1.0 - uv.y;
  }
  return uv;
}

float getHeight(vec2 lonlat0) {
  vec2 uv = getUV(lonlat0);

  return getTerrainHeight(uv);
}

float getWater(vec2 lonlat0) {
  vec2 uv = getUV(lonlat0);
  return getCurrentWater(uv).r;
}

float getWater2(vec2 lonlat0) {
  vec2 uv = getUV(lonlat0);
  return getLastWater(uv).r;
}

vec3 getWorldPosition(vec3 pos) {
  vec3 rtcCenter = Weget_rtcCenter();
  return we_cartesian3FromRadians(pos) - rtcCenter;
}

void main() {
  vec4 worldExtent = Weget_extent();
  float numLon = Weget_numLon();
  float numLat = Weget_numLat();
  float height = Weget_height();
  float extrusionScale = Weget_extrusionScale();
  float normalFactor = Weget_normalFactor();
  float numVertexs = numLon * numLat;
  float position1 = mod(position,numVertexs);
  float face = floor(position / numVertexs);

  float r = floor(position1/(numLon));
  float c = floor(mod(position1,numLon));

  vec2 ws = worldExtent.xy;
  vec2 en = worldExtent.zw;
  float dx = (en.x - ws.x) / (numLon - 1.0 + 1.0);// 0_1_2, 2 is edge
  float dy = (en.y - ws.y) / (numLat - 1.0 + 1.0);

  vec3 pos = vec3(0.0);

  vec2 lonlat0 = ws + vec2(dx * c,dy * r);
  vec2 lonlat1 = ws + vec2(dx * (c + 1.0),dy * r);
  vec2 lonlat2 = ws + vec2(dx * (c + 1.0),dy * (r + 1.0));
  vec2 lonlat3 = ws + vec2(dx * c,dy * (r + 1.0));

  vec2 lonlat4 = ws + vec2(dx * (c - 1.0),dy * (r - 0.0));
  vec2 lonlat5 = ws + vec2(dx * (c - 1.0),dy * (r - 1.0));
  vec2 lonlat6 = ws + vec2(dx * (c - 0.0),dy * (r - 1.0));

  vec2 uv = vec2(c / (numLon - 1.0),r / (numLat - 1.0));
  bool shouldFlipY = Weget_shouldFlipY() > 0.0;
  if(shouldFlipY){
    uv.y = 1.0 - uv.y;
  }

  vec3 normal = vec3(0.0,0.0,1.0);

  float value0 = getHeight(lonlat0) * extrusionScale;
  float value1 = getHeight(lonlat1) * extrusionScale;
  float value2 = getHeight(lonlat2) * extrusionScale;
  float value3 = getHeight(lonlat3) * extrusionScale;
  float value4 = getHeight(lonlat4) * extrusionScale;
  float value5 = getHeight(lonlat5) * extrusionScale;
  float value6 = getHeight(lonlat6) * extrusionScale;

  float elev0 = getWater(lonlat0);
  float elev1 = getWater(lonlat1);
  float elev2 = getWater(lonlat2);
  float elev3 = getWater(lonlat3);
  float elev4 = getWater(lonlat4);
  float elev5 = getWater(lonlat5);
  float elev6 = getWater(lonlat6);

  float height0 = elev0 + value0;
  float height1 = elev1 + value1;
  float height2 = elev2 + value2;
  float height3 = elev3 + value3;
  float height4 = elev4 + value4;
  float height5 = elev5 + value5;
  float height6 = elev6 + value6;

  vec3 worldCoords0 = getWorldPosition(vec3(lonlat0,elev0 + elev0 * normalFactor));
  vec3 worldCoords1 = getWorldPosition(vec3(lonlat1,elev1 + elev1 * normalFactor));
  vec3 worldCoords2 = getWorldPosition(vec3(lonlat2,elev2 + elev2 * normalFactor));
  vec3 worldCoords3 = getWorldPosition(vec3(lonlat3,elev3 + elev3 * normalFactor));
  vec3 worldCoords4 = getWorldPosition(vec3(lonlat4,elev4 + elev4 * normalFactor));
  vec3 worldCoords5 = getWorldPosition(vec3(lonlat5,elev5 + elev5 * normalFactor));
  vec3 worldCoords6 = getWorldPosition(vec3(lonlat6,elev6 + elev6 * normalFactor));

  vec3 normal1 = normalize(cross(worldCoords2 - worldCoords1,worldCoords0 - worldCoords1));
  vec3 normal2 = normalize(cross(worldCoords0 - worldCoords3,worldCoords2 - worldCoords3));
  vec3 normal3 = normalize(cross(worldCoords0 - worldCoords6,worldCoords5 - worldCoords6));
  vec3 normal4 = normalize(cross(worldCoords5 - worldCoords4,worldCoords0 - worldCoords4));
  vec3 normal5 = normalize(cross(worldCoords3 - worldCoords0,worldCoords4 - worldCoords0));
  vec3 normal6 = normalize(cross(worldCoords6 - worldCoords0,worldCoords1 - worldCoords0));

  normal = normalize(
    normal1 +
    normal2 +
    normal3 +
    normal4 +
    normal5 +
    normal6
  );
normal = normal1;

  //top
  if(face == 0.0) {
    height += height0;
  }
  else if(face == 1.0) {
    height += height1;
    lonlat0 = lonlat1;
  }
  else if(face == 2.0) {
    height += height2;
    lonlat0 = lonlat2;
  }
  else if(face == 3.0) {
    height += height3;
    lonlat0 = lonlat3;
  }


  v_color = vec4(1.0);
  v_color.b *= step(elev0-value0,0.0);
  // v_color.a = 1.0 - step(elev0-value0,0.0);
  vec3 worldCoords = getWorldPosition(vec3(lonlat0,height));
  gl_Position = czm_modelViewProjection * vec4(worldCoords,1.0);
  v_positionEC = (czm_modelView * vec4(worldCoords,1.0)).xyz;
  v_normalEC = czm_normal * normal;
  v_normalEC = normal;
  v_textureCoords = getUV(lonlat0);
  v_positionMC = worldCoords;
}
`

export const fsSource = `
uniform sampler2D flows,normalMap;
in vec2 v_textureCoords;
in vec3 v_positionEC;
in vec3 v_normalEC;
in vec4 v_color;
in vec3 v_positionMC;

float specularIntensity = 0.25;
float animationSpeed = 0.1;
float frequency = 512.0;
float fadeFactor = 1.0;
vec4 blendColor = vec4(1.0, 1.0, 1.0, 0.0);

float angleBetweenVectors(vec2 v1, vec2 v2) {
    float dotProduct = dot(normalize(v1), normalize(v2));
    float angle = acos(clamp(dotProduct, -1.0, 1.0));
    return angle;
}

czm_material computeWaterColor(vec4 baseWaterColor,czm_materialInput materialInput,float specularMapValue,
float amplitude,float angle)
{
    czm_material material = czm_getDefaultMaterial(materialInput);

    vec2 uv = v_textureCoords;

    float time = czm_frameNumber * animationSpeed;
    // fade is a function of the distance from the fragment and the frequency of the waves
    float fade = max(1.0, (length(materialInput.positionToEyeEC) / 10000000000.0) * frequency * fadeFactor);

    // note: not using directional motion at this time, just set the angle to 0.0;
    vec4 noise = czm_getWaterNoise(normalMap, uv * frequency, time, angle);
    vec3 normalTangentSpace = noise.xyz * vec3(1.0, 1.0, (1.0 / amplitude));

    // fade out the normal perturbation as we move further from the water surface
    normalTangentSpace.xy /= fade;

    // attempt to fade out the normal perturbation as we approach non water areas (low specular map value)
    normalTangentSpace = mix(vec3(0.0, 0.0, 50.0), normalTangentSpace, specularMapValue);

    normalTangentSpace = normalize(normalTangentSpace);

     // get ratios for alignment of the new normal vector with a vector perpendicular to the tangent plane
    float tsPerturbationRatio = clamp(dot(normalTangentSpace, vec3(0.0, 0.0, 1.0)), 0.0, 1.0);

    // fade out water effect as specular map value decreases
    material.alpha = mix(blendColor.a, baseWaterColor.a, specularMapValue) * specularMapValue;

    // base color is a blend of the water and non-water color based on the value from the specular map
    // may need a uniform blend factor to better control this
    material.diffuse = mix(blendColor.rgb, baseWaterColor.rgb, specularMapValue);

    // diffuse highlights are based on how perturbed the normal is
    material.diffuse += (0.1 * tsPerturbationRatio);

    material.diffuse = material.diffuse;

    material.diffuse = material.diffuse;

    material.normal = normalize(materialInput.tangentToEyeMatrix * normalTangentSpace);

    material.specular = specularIntensity;
    material.shininess = 10.0;

    return material;
}

vec3 getnormal(){
  vec2 uv = v_textureCoords;

  float flowTexSize = Weget_numLon();
  float s = 1.0/flowTexSize;
  vec2 center_uv = uv;
  vec2 right_uv = center_uv + vec2(s, 0.0);
  vec2 top_uv = center_uv + vec2(0.0, s);
  vec2 topright_uv = center_uv + vec2(s, s);
  vec2 center_pos = texture(flows, center_uv).xy;
  vec2 right_pos = texture(flows, right_uv).xy;
  vec2 top_pos = texture(flows, top_uv).xy;
  vec2 topright_pos = texture(flows, topright_uv).xy;

  float factor = 32.0;
  vec2 off = mod(uv, s);

  float factorN = factor * 1.0;

  vec3 center = normalize(texture(normalMap, uv*factorN-center_pos*2.0).xyz*2.0-1.0);
  vec3 right = normalize(texture(normalMap, uv*factorN-right_pos*2.0).xyz*2.0-1.0);
  vec3 top = normalize(texture(normalMap, uv*factorN-top_pos*2.0).xyz*2.0-1.0);
  vec3 topright = normalize(texture(normalMap, uv*factorN-topright_pos*2.0).xyz*2.0-1.0);

  vec3 normal1 = mix(center, right, off.x/s);
  vec3 normal2 = mix(top, topright, off.x/s);
  vec3 normal = mix(normal1, normal2, off.y/s);
  // return vec3(center);
  return normalize(normal*vec3(1.0, 0.2, 1.0));
}

void main() {
      float maxWaterHeight = Weget_maxWaterHeight();
      vec2 uv = v_textureCoords;
      vec3 w = texture(currentWater, uv).xyz;
      float weSpeedFactor = Weget_speedFactor();
      float speed_factor = clamp(length(w.yz) /maxWaterHeight * weSpeedFactor, 0.0, 1.0);
      float depth_factor = clamp(w.x/maxWaterHeight * 1.2, 0.0, 1.0);

      vec3 base_normal = v_normalEC;
      vec3 detail_normal = getnormal();

      vec3 normal = normalize(mix(base_normal*0.5+detail_normal*0.5, detail_normal, speed_factor));

      vec3 lightdir = czm_lightDirectionEC;
      vec3 eye_normal = czm_normal * v_normalEC;
      vec3 specular_normal = reflect(eye_normal, normalize(normal * vec3(1.0, 0.35, 1.0)));
      float lambert = pow(max(0.0, dot(specular_normal, lightdir)), 0.5);
      float specular = pow(lambert, 20.0);

      vec4 color = vec4(1.0);
      vec3 deep = Weget_deepColor();
      vec3 turbulent = Weget_turbulentColor();
      color.rgb = mix(turbulent, deep, sqrt(clamp(depth_factor, 0.0, 1.0)));
      color.rgb = mix(color.rgb, vec3(1.0, 1.0, 1.0), clamp(pow(speed_factor*2.0, 3.0), 0.0, 1.0));

      czm_materialInput materialInput;
      materialInput.st = uv;
      materialInput.positionToEyeEC = -v_positionEC;
      materialInput.tangentToEyeMatrix = czm_eastNorthUpToEyeCoordinates(vec3(1.0), normalize(czm_normal * v_normalEC));

      float alpha = clamp(depth_factor * 120.0,0.0,1.0);

      vec2 velocity = w.yz;
      float rad = angleBetweenVectors(velocity,vec2(0.0,-1.0));
      if(velocity.x < 0.0){
          rad = czm_twoPi - rad;
      }
      czm_material material = computeWaterColor(color, materialInput, alpha, 10.0 * depth_factor,0.0);
      color.rgb = material.diffuse;
      color.a = material.alpha;
      color.rgb = WePhong(color.rgb,material.specular,normalize(-v_positionEC),czm_lightDirectionEC,
        normalize(material.normal * 0.3 + 0.7 * normal));

      // color = vec4(1.0);
      // vec3 normalEC = v_normalEC;
      // color.rgb = WePhong(color.rgb,0.1,normalize(-v_positionEC),czm_lightDirectionEC,
      //   normalize(normalEC));

      if(color.a == 0.0) discard;
      out_FragColor = color;
  }
`
export default { vsSource, fsSource }
